#pragma once

#include <map>

/*
This class stores settings for:
	Vocoding
	PitchTracker
	Carrier
	Player
*/
class Settings
{
public:
	Settings(void);
	~Settings(void);
	void SetDefault();

	int bandCount;//how many bands are used in vocoding (should be a power of 2)
	int windowLength;//how many samples are in each window (should be a power of 2)
	int overlapLength;//how much window overlapping is done (should be <= windowLength/2)
	int samplingRate;//how many samples per seconds
	bool normalizeVocoder;//should vocoder be normalized (raises amplitude to normal hearing levels if true)

	/*
	See WaveletPitchProcessor for explanation on threshold parameters
	*/
	class PitchTrackerSettings
	{
	public:
		PitchTrackerSettings(){}
		~PitchTrackerSettings(){}
		double amplitudeThreshold;
		double noiseThreshold;
	};
	PitchTrackerSettings* GetPitchTracker(){return &pitchTracker;}

	class CarrierSettings
	{
	public:
		CarrierSettings(){}
		~CarrierSettings(){}
		int intensityVariation;//The amount by which amplitude of each wave component is allowed to randomly vary from its set intensity
		int frequency;//Currently assigned frequency (e.g. by a FrequencyProvider)
		int frequencyVariation;//The amount by which the frequency of each wave component is allowed to randomly vary from the current frequency

		/*
		The following settings all describe intensity of each wave component part.
		Each part's intensity is relative to the intensity of each other part's intensity, i.e. 'own intensity' divided by 'sum of all intensities'.
		*/
		int modulator;
		int brownNoise;
		int whiteNoise;
		int triangular;
		int square;
		int sawtooth;
		int sine;
		int random;
		int function1;
		int function2;
		int function3;
		int freq2;
		int freq3;
		int freq4;
		int freq5;
		int freq6;
		int freq7;
		int freq8;
		int freq9;
	};
	CarrierSettings* GetCarrier(){return &carrier;}

	class PlayerSettings
	{
	public:
		enum StreamType
		{
			Modulator = 0,
			Carrier,
			Vocoder
		};
		PlayerSettings(){}
		~PlayerSettings(){}
		bool shouldRecord;//Should the player be recording the currently played sound
		StreamType streamType;//What should be played (modulator, carrier or vocoded output)
	};
	PlayerSettings* GetPlayer(){return &player;}

	class VocoderSettings
	{
	public:
		VocoderSettings(){}
		~VocoderSettings(){}

		/*
		Experimental settings that will probably be thrown away.
		*/
		bool applySilence;
		int absSilenceThreshold;
		int minSilenceSamples;
		bool normalize;
		bool mixWithModulator;
		bool useModulatorAmplitude;
	};
	VocoderSettings* GetVocoder(){return &vocoder;}

private:
	PitchTrackerSettings pitchTracker;
	CarrierSettings carrier;
	PlayerSettings player;
	VocoderSettings vocoder;
};

/*
Class that provides updates to settings, that are then reflected in output, e.g. by carrier or vocoder.
Can e.g. be implemented by a class that reads settings from ui components, or that reads settings sent via messaging of some sort.
*/
class SettingsProvider
{
public:
	SettingsProvider(void){}
	~SettingsProvider(void){}

	/*
	The SettingsProvider should update 'settings' if something has changed since the last time it was called.
	*/
	virtual void UpdateSettings(Settings* settings) = 0;
};
